/*
 * Copyright 2001-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package code.buildit.plugin.processor;

import code.buildit.plugin.fileconfig.JavaFile;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;

import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;

public class CreateBuilderClassCommand implements Runnable {
    private static final String SELECT_DIR_MSG = "Which directory should the builder be in?";
    private static final String SELECT_DIR_TITLE = "Choose directory";

    private PsiClass aClass;
    private JavaFile javaFile;
    private Module moduleForPsiElement;
    private PsiClass psiClass;


    public CreateBuilderClassCommand(PsiClass aClass, JavaFile javaFile) {
        this.aClass = aClass;
        this.javaFile = javaFile;
        this.moduleForPsiElement = ModuleUtil.findModuleForPsiElement(aClass);
    }

    public void run() {

        try {
            PsiDirectory psiDirectory = getBuilderDirectory(javaFile.getAbsoluteFileName());
            if (psiDirectory == null) return;
            psiClass = psiDirectory.createClass(javaFile.getFileName());
            //copy fields and then create methods;
        } catch (IncorrectOperationException e) {
            e.printStackTrace();
        }

    }

    private PsiDirectory getRootDirectory() {

        VirtualFile[] sourceRoots = ModuleRootManager.getInstance(moduleForPsiElement).getSourceRoots();
        String[] dirStrs = toStringArray(sourceRoots);
        int choice = Messages.showChooseDialog(aClass.getProject(), SELECT_DIR_MSG, SELECT_DIR_TITLE,
                Messages.getQuestionIcon(), dirStrs, dirStrs[0]);

        if (choice == -1)
            return null;
        VirtualFile virtualFile = sourceRoots[choice];

        return aClass.getManager().findDirectory(virtualFile);
    }

    private String[] toStringArray(VirtualFile[] sourceRoots) {
        List<String> elements = new ArrayList<String>();
        for (VirtualFile sourceRoot : sourceRoots) {
            elements.add(sourceRoot.getPath());
        }
        return elements.toArray(new String[sourceRoots.length]);
    }

    private PsiDirectory getDirectoryFor(PsiDirectory directory, String name) throws IncorrectOperationException {
        PsiDirectory psiDirectory = directory.findSubdirectory(name);
        if (psiDirectory != null)
            return psiDirectory;
        return directory.createSubdirectory(name);
    }

    private PsiDirectory moveToToggleDirectory(String toggledName, PsiDirectory directory) throws IncorrectOperationException {
        String packageName = new JavaFile(toggledName).getPackageName();
        StringTokenizer tokenizer = new StringTokenizer(packageName, ".");
        while (tokenizer.hasMoreTokens()) {
            String name = tokenizer.nextToken();
            directory = getDirectoryFor(directory, name);
        }
        return directory;
    }

    private PsiDirectory getBuilderDirectory(String toggledName) throws IncorrectOperationException {
        PsiDirectory directory = getRootDirectory();
        if (directory == null)
            return null;
        return moveToToggleDirectory(toggledName, directory);

    }

    public PsiClass getPsiClass() {
        return psiClass;
    }
}
